package com.qingfeng.client.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qingfeng.client.DO.GoodsInfoDo;
import com.qingfeng.client.DO.OrderDetailDo;
import com.qingfeng.client.DO.PreTradeDo;
import com.qingfeng.client.DO.TransformFeeDo;
import com.qingfeng.client.VO.*;
import com.qingfeng.client.bean.*;
import com.qingfeng.client.dao.*;
import com.qingfeng.client.util.MakeOrderNum;
import com.qingfeng.client.util.Page;
import com.qingfeng.client.util.TradeEnum;
import com.qingfeng.coupon.Do.CouponDetail;
import com.qingfeng.coupon.service.CouponService;
import com.qingfeng.exception.LsException;
import com.qingfeng.util.CodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.ORB;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.annotation.Resource;
import javax.swing.plaf.IconUIResource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author zhangyuefei
 * @version 1.0
 * @date 2020/1/6 4:51 下午
 */
@Slf4j
@Service
public class OrderService {

    @Resource
    private TradeMapper tradeDao;

    @Resource
    private OrderGoodsMapper orderGoodsDao;

    @Resource
    private GoodsMapper goodsDao;

    @Resource
    private OrderStoreMapper orderStoreDao;

    @Resource
    private StoreMapper storeMapper;
    @Resource
    private LogisticsMapper logisticsMapper;

    @Resource
    private LogisticsMapper logisticsDao;

    @Resource
    private ShippingAddressMapper shippingAddressDao;

    @Resource
    private LogisticsCompanyMapper logisticsCompanyDao;

    @Resource
    private ShoppingCartMapper shoppingCartMapper;

    @Resource
    private PostageAddressMapper postageAddressMapper;

    @Resource
    private PostageTemplateMapper postageTemplateMapper;

    @Autowired
    private DealQueueService dealQueueService;

    @Autowired
    private CouponService couponService;

    @Autowired
    private ActivityService activityService;


    public void confirm(Long orderStoreId) {
        OrderStore orderStore = orderStoreDao.selectById(orderStoreId);
        orderStore.setStat(TradeEnum.TRADE_FINISH.getCode());
        orderStore.setFinishTime((int) (System.currentTimeMillis() / 1000));
        orderGoodsDao.updateStatByOrderStoreId(TradeEnum.TRADE_FINISH.getCode(), orderStoreId);
        orderStoreDao.updateById(orderStore);
    }


    /**
     * 获取商品基本信息，用于展示
     *
     * @param orderGoodsVos
     */
    public PreTradeDo preTrade(@RequestBody List<OrderGoodsVo> orderGoodsVos, Long buyerId) {

        Trade trade = initTrade(buyerId);

        List<GoodsInfoDo> goodsInfoDos = goodsDao.getGoodsInfoByGoodsIds(orderGoodsVos);
        goodsInfoDos.forEach(gdo -> {
            orderGoodsVos.forEach(ovo -> {
                if (gdo.getGoodsId().equals(ovo.getGoodsId())) {
                    gdo.setNum(ovo.getNum());
                    gdo.setCartId(ovo.getCartId());
                }

            });
        });
        PreTradeDo preTradeDo = new PreTradeDo();
        preTradeDo.setGoodsInfoDos(goodsInfoDos);
        preTradeDo.setTradeId(trade.getId());
        preTradeDo.setCouponDetails(couponService.orderUsableCoupon(preTradeDo, buyerId));
        return preTradeDo;
    }

    /**
     * 创建订单
     * 1.扣除商品数量，检查商品库存是否为负数，如果是则返回商品库存不足
     * 3.判断是否来自购物车，如果是则更新购物车信息
     * 2.获取物流信息，计算运费
     * 4.新增trade
     * 5.新增ordetStore
     * 6.新增orderGoods
     * 7.更新trade
     * 8.添加订单消息到消息队列中
     * 9.返回订单trade信息
     *
     * @param tradeVo
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Trade createTrade(TradeVo tradeVo) {
        int totalFreight = 0;
        int totalPrice = 0;
        int totalSaveMoney = 0;
        Trade trade = tradeDao.selectById(tradeVo.getTradeId());
        if (trade.getTradeStat() != TradeEnum.TRADE_PRE.getCode()) {
            throw new LsException(CodeEnum.ERROR, "请勿重复提交订单");
        }

        ShippingAddress shippingAddress = null;
        LogisticsCompany logisticsCompany = null;
        //获取邮寄信息
        if (tradeVo.getShippingAddressId() != null) {
            shippingAddress = shippingAddressDao.selectById(tradeVo.getShippingAddressId());
        }
        //获取自提信息
        if (tradeVo.getLogisticsCompanyId() != null) {
            logisticsCompany = logisticsCompanyDao.selectById(tradeVo.getLogisticsCompanyId());
        }

        for (OrderStoreVo orderStoreVo : tradeVo.getOrderStoreVos()) {
            //获取该店铺下所有购买的商品信息
            List<GoodsInfoDo> goodsInfoDos = goodsDao.getGoodsInfoByGoodsIds(orderStoreVo.getGoods());
            boolean allInStore = goodsInfoDos.stream().allMatch(item -> item.getStoreId().equals(orderStoreVo.getStoreId()));
            if (!allInStore) {
                throw new LsException(CodeEnum.ERROR, "参数错误,部分商品不在该店铺中");
            }
            if (goodsInfoDos.size() != orderStoreVo.getGoods().size()) {
                throw new LsException(CodeEnum.ERROR, "订单中含有已下架商品，orderSize："
                        + orderStoreVo.getGoods().size() + " goodsSize:" + goodsInfoDos.size());
            }
            //如果物流选择邮寄，则需要判断商品中是否有商品只能自提
            if (shippingAddress != null) {
                boolean onlyPick = goodsInfoDos.stream().anyMatch(
                        gdo -> gdo.getLogisticsType() != null && gdo.getLogisticsType().equals(2));
                if (onlyPick) {
//                    throw new LsException(CodeEnum.ERROR,"存在只能自提商品，请重新选择收货地址或分开购买");
                    if (goodsInfoDos.size() <= 1) {
                        throw new LsException(CodeEnum.ERROR, "该商品不支持物流配送");
                    } else {
                        throw new LsException(CodeEnum.ERROR, "订单中多个商品配送方式不同，请重新下单");
                    }
                }
            } else {
                boolean onlySend = goodsInfoDos.stream().anyMatch(
                        gdo -> gdo.getLogisticsType() != null && gdo.getLogisticsType().equals(1));
                if (onlySend) {
//                    throw new LsException(CodeEnum.ERROR,"存在只能邮寄商品，请重新选择收货地址或分开购买");
                    if (goodsInfoDos.size() <= 1) {
                        throw new LsException(CodeEnum.ERROR, "该商品不支持自提");
                    } else {
                        throw new LsException(CodeEnum.ERROR, "订单中多个商品配送方式不同，请重新下单");
                    }
                }
            }
            //设置goodsInfoDos 的num,为orderGoodsVos中的num
            goodsInfoDos.forEach(gdo -> {
                orderStoreVo.getGoods().forEach(ovo -> {
                    if (ovo.getGoodsId().equals(gdo.getGoodsId())) {
                        gdo.setNum(ovo.getNum());
                    }
                });
            });

            //计算运费
            int transformFee = sumTransformFee(goodsInfoDos, shippingAddress, orderStoreVo.getStoreId());
            // 计算优惠券，并且设置单个商品的优惠价格
            CouponDetail couponDetail = couponService.getCouponMoney(goodsInfoDos,
                    orderStoreVo.getCouponId(), tradeVo.getBuyerId());
            if (couponDetail != null) {
                couponService.useCoupon(couponDetail.getCouponId());
                totalSaveMoney += couponDetail.getDiscountQuota();
//                orderStoreVo.setCouponName(couponDetail.getName());
                orderStoreVo.setSaveMoney(couponDetail.getDiscountQuota());
                orderStoreVo.setCouponId(couponDetail.getCouponId());
            } else {
                orderStoreVo.setSaveMoney(0);
//                orderStoreVo.setCouponName(null);
            }

            //计算商品总价
            int price = sumPrice(goodsInfoDos);
            // 计算优惠之后的价格，如果价格低于0 则为0.01；
            if (couponDetail != null) {
                price = price - couponDetail.getDiscountQuota();
                if (price < 0) {
                    price = 0;
                }
            }
            totalFreight += transformFee;
            totalPrice += price;

            //主要数据库操作部分，更新店铺订单
            //更新库存
            updateGoodsNum(goodsInfoDos);
            //插入物流信息
            Logistics logistics = initLogistics(logisticsCompany, shippingAddress, transformFee, tradeVo);

            //插入店铺订单信息
            Long orderStroeId = initStoreOrder(transformFee, price, tradeVo.getBuyerId(), trade, logistics.getId()
                    , tradeVo.getWx(), orderStoreVo);
            //插入单品订单信息
            initGoodsOrder(goodsInfoDos, trade.getId(), orderStoreVo.getComment(), orderStroeId);
            //删除购物车信息
            deleteShoppingCart(orderStoreVo.getGoods(), tradeVo.getBuyerId());
            //@todo 临时活动,给领导送优惠券送礼
            activityService.removeCode(orderStoreVo.getCouponName(),orderStoreVo.getGoods().get(0).getGoodsId()+"");
        }
        //更新交易信息
        trade.setFreight(totalFreight);
        if ((totalPrice + totalFreight) <= 0) {
            // 如果总付款金额为0或者负数则强行支付1分钱
            trade.setPayment(1);
        } else {
            trade.setPayment(totalPrice + totalFreight);
        }

        trade.setSaveMoney(totalSaveMoney);
        trade.setTradeStat(TradeEnum.TRADE_WAIT_PAY.getCode());
        trade.setCreateTime((int) (System.currentTimeMillis() / 1000));
        tradeDao.updateById(trade);
        //加入支付超时处理队列
        dealQueueService.add(trade);
        return trade;
    }


    /**
     * 删除购物车
     *
     * @param orderGoodsVos
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteShoppingCart(List<OrderGoodsVo> orderGoodsVos, @NotNull Long buyerId) {
        List<Long> carIds = orderGoodsVos.stream()
                .map(OrderGoodsVo::getCartId).filter(x -> x != null)
                .collect(Collectors.toList());
        if (carIds != null && carIds.size() > 0) {
            shoppingCartMapper.deleteByBuyerIdAndId(buyerId, carIds);
        }
    }


    /**
     * 计算单个店铺所有商品的运费
     * 1.比对收货地址code，获取运费模版
     * 2.计算商品总价格，看是否满足包邮条件
     * 3.如果不满足包邮条件计算商品运费
     *
     * @param goodsInfoDos    商品信息列表
     * @param shippingAddress 邮寄地址列表，如果为null表示到店自取，则邮费为0；
     * @return
     */
    private int sumTransformFee(List<GoodsInfoDo> goodsInfoDos, ShippingAddress shippingAddress, int storeId) {
        int transformFee = 0;
//        自提商品，无须计算运费
        if (shippingAddress == null) {
            return 0;
        }
        if (goodsInfoDos.size()==1 && goodsInfoDos.get(0).getGoodsId().equals(21L)){
            //@todo 将来需要删除 ，21号商品是送给客户的不需要运费
            return 0;
        }
        //计算运费
        PostageAddress postageAddress =
                postageAddressMapper.selectOneByStoreIdAndCode(storeId, shippingAddress.getCode() / 100 * 100);
//       如果未找到 二级位置，则去寻找一级位置
        if (postageAddress == null) {
            postageAddress =
                    postageAddressMapper.selectOneByStoreIdAndCode(storeId, shippingAddress.getCode() / 10000 * 10000);
        }
        PostageTemplate postageTemplate;
        if (postageAddress == null) {
            postageTemplate = postageTemplateMapper.selectOneByStoreIdAndDef(storeId, true);
        } else {
            postageTemplate = postageTemplateMapper.selectById(postageAddress.getTemplateId());
        }

        if (postageTemplate == null) {
            throw new LsException(CodeEnum.ERROR, "请联系管理员，设置物流邮费");
        }

        int sumPrice = goodsInfoDos.stream().mapToInt(goodsinfo -> goodsinfo.getPrice() * goodsinfo.getNum()).sum();
        if (postageTemplate.getFreePrice() != null && sumPrice >= postageTemplate.getFreePrice()) {
            return 0;
        }

        sumPrice = 0;
        int sumWeight = goodsInfoDos.stream().mapToInt(item -> item.getWeight() * item.getNum()).sum();
        if (sumWeight <= postageTemplate.getFirstWeight()) {
            return postageTemplate.getFirstPrice();
        } else {
            //小数部分四舍五入
            int secondPrice = ((int) Math.ceil(
                    (sumWeight - postageTemplate.getFirstWeight()) * 1.0 / postageTemplate.getSecondWeight()
            )) * postageTemplate.getSecondPrice();
            return postageTemplate.getFirstPrice() + secondPrice;


        }
    }

    /**
     * 计算所有商品邮费
     *
     * @param vo
     * @return
     */
    public List<TransformFeeDo> getTransformFee(TransformFeeVo vo) {
        List<TransformFeeDo> list = new ArrayList<>();
        ShippingAddress shippingAddress = shippingAddressDao.selectById(vo.getAddressId());
        List<OrderStoreVo> orderStore = vo.getOrderStore();
        for (OrderStoreVo orderStoreVo : orderStore) {

            TransformFeeDo transformFeeDo = new TransformFeeDo();
            transformFeeDo.setStoreId(orderStoreVo.getStoreId());

            List<GoodsInfoDo> goodsInfoDos = goodsDao.getGoodsInfoByGoodsIds(orderStoreVo.getGoods());
            //设置goodsInfoDos 的num,为orderGoodsVos中的num
            goodsInfoDos.forEach(gdo -> {
                orderStoreVo.getGoods().forEach(ovo -> {
                    if (ovo.getGoodsId().equals(gdo.getGoodsId())) {
                        gdo.setNum(ovo.getNum());
                    }
                });
            });
            int postage = sumTransformFee(goodsInfoDos, shippingAddress, orderStoreVo.getStoreId());
            transformFeeDo.setTransformFee(postage);

            list.add(transformFeeDo);
        }
        return list;
    }

    /**
     * 计算商品单价累计价格
     *
     * @param goodsInfoDos
     * @return
     */
    private int sumPrice(List<GoodsInfoDo> goodsInfoDos) {
        return goodsInfoDos.stream().mapToInt(item -> {
            return item.getNum() * item.getPrice();
        }).sum();
    }


    /**
     * 更新商品数量信息
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateGoodsNum(List<GoodsInfoDo> goodsInfoDos) {
        goodsDao.updateGoodsNum(goodsInfoDos);
        List<Goods> goods = goodsDao.selectByIdList(goodsInfoDos);
        List<Goods> list = goods.stream().filter(item -> item.getCanSellSize() < 0).collect(Collectors.toList());
        if (list.size() > 0) {
            throw new LsException(CodeEnum.ERROR, "库存不足");
        }
    }

    /**
     * 新增一条交易记录
     * 更新trade
     *
     * @param buyerId
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Trade initTrade(Long buyerId) {
        //创建交易
        Trade tradeBean = new Trade();
        //交易号
        tradeBean.setId(null);
        //订单号
        MakeOrderNum makeOrderNum = new MakeOrderNum();
        tradeBean.setCode(makeOrderNum.makeOrderNum());
        //购买者id
        tradeBean.setBuyerId(buyerId);
        //订单处理人
        //优惠
        tradeBean.setSaveMoney(0);
        //交易状态
        tradeBean.setTradeStat(TradeEnum.TRADE_PRE.getCode());
        //创建时间
        tradeBean.setCreateTime((int) (System.currentTimeMillis() / 1000));
        tradeDao.insert(tradeBean);
        return tradeBean;
    }

    /**
     * 新增多条店铺订单信息
     * 更新orderStore
     */
    public Long initStoreOrder(int freight, int price, Long buyerId, Trade trade,
                               long logisticsId, String wx, OrderStoreVo orderStoreVo) {
        OrderStore orderStore = new OrderStore();
        orderStore.setBuyerId(buyerId);
        orderStore.setStoreId(orderStoreVo.getStoreId());
        orderStore.setTradeId(trade.getId());
        orderStore.setCode(trade.getCode());
        orderStore.setLogisticsId(logisticsId);
        orderStore.setStat(1);
        orderStore.setComment(orderStore.getComment());
        orderStore.setWeChat(wx);
        orderStore.setFreight(freight);
        orderStore.setPrice(price + 0L);
        orderStore.setCreateTime((int) (System.currentTimeMillis() / 1000));
        orderStore.setCouponId(orderStoreVo.getCouponId());
        orderStore.setCouponName(orderStoreVo.getCouponName());
        orderStore.setSaveMoney(orderStoreVo.getSaveMoney());
        orderStoreDao.insert(orderStore);
        return orderStore.getId();
    }

    /**
     * 新增多条商品订单
     * 更新orderGoods
     */
    public List<GoodsInfoDo> initGoodsOrder(List<GoodsInfoDo> goodsInfoDos, Long tradeId
            , String comment, Long orderStoreId) {
        List<OrderGoods> orderGoodsList = new ArrayList<>();
        for (GoodsInfoDo item : goodsInfoDos) {
            OrderGoods orderGoods = new OrderGoods();
            orderGoods.setOrderStoreId(orderStoreId);
            orderGoods.setTradeId(tradeId);
            orderGoods.setPrice(item.getPrice());
            orderGoods.setGoodsCommonId(item.getGoodsCommonId());
            orderGoods.setGoodsId(item.getGoodsId());
            orderGoods.setComment(comment);
            orderGoods.setGoodsAttrs(item.getAttrs());
            orderGoods.setGoodsCode(item.getGoodsCode());
            orderGoods.setGoodsName(item.getName());
            orderGoods.setGoodsPic(item.getPic1());
            orderGoods.setNum(item.getNum());
            orderGoods.setStat(1);
            orderGoods.setStoreId(item.getStoreId());
            orderGoods.setOrderStoreId(orderStoreId);
            if (item.getSaveMoney() == null) {
                orderGoods.setSaveMoney(0);
            } else {
                orderGoods.setSaveMoney(item.getSaveMoney());
            }
            orderGoods.setTotalPrice(item.getPrice() * item.getNum() - orderGoods.getSaveMoney());
            orderGoodsList.add(orderGoods);
        }
        orderGoodsDao.insertList(orderGoodsList);
        return goodsInfoDos;
    }

    private int getNum(List<OrderGoodsVo> list, long goodsId) {
        for (OrderGoodsVo orderGoodsVo : list) {
            if (orderGoodsVo.getGoodsId() == goodsId) {
                return orderGoodsVo.getNum();
            }
        }
        return 0;
    }

    /**
     * 新增物流数据
     */
    public Logistics initLogistics(LogisticsCompany logisticsCompany, ShippingAddress shippingAddress, int price, TradeVo tradeVo) {
        Logistics logistics = new Logistics();
        logistics.setState(1);
        logistics.setCreateTime((int) (System.currentTimeMillis() / 1000));
        logistics.setPrice(price);
        logistics.setCreateId(tradeVo.getBuyerId());
        if (logisticsCompany == null) {
            //物流
            logistics.setType(1);
            logistics.setRecvMobile(shippingAddress.getMobile());
            logistics.setRecvName(shippingAddress.getUsername());
            logistics.setDesAddress(shippingAddress.getAddress() + "," + shippingAddress.getDetail());
            logistics.setDesCode(shippingAddress.getCode());
        } else {
            //自提
            logistics.setType(2);
            logistics.setLogisticsName(logisticsCompany.getName());
            logistics.setSrcAddress(logisticsCompany.getAddress());
            logistics.setDesAddress(logisticsCompany.getAddress());
            logistics.setSendMobile(logisticsCompany.getContactsMobile());
            logistics.setSendName(logisticsCompany.getContactsName());
            logistics.setRecvMobile(tradeVo.getRecvMobile());
            logistics.setRecvName(tradeVo.getRecvName());
        }
        logisticsDao.insert(logistics);
        return logistics;
    }


    /**
     * 取消付款,处理消息队列中的内容
     * 删除所有相关交易记录
     *
     * @param tradeId
     */
    public void canclePay(long tradeId) {
        Trade trade = tradeDao.selectById(tradeId);
        if (trade.getTradeStat().equals(TradeEnum.TRADE_WAIT_PAY.getCode())) {
            //先恢复库存
            System.out.println("取消付款");
            List<OrderGoods> list = orderGoodsDao.selectByTradeId(tradeId);
            for (OrderGoods goods : list) {
                goodsDao.recvGoodsById(goods.getNum(), goods.getGoodsId());
            }
            orderGoodsDao.canclePayByTradeId(tradeId);
            orderStoreDao.canclePayByTradeId(tradeId);
            tradeDao.canclePayByTradeId(tradeId);
            List<OrderStore> list1 = orderStoreDao.selectByTradeId(tradeId);
            if (!CollectionUtils.isEmpty(list1)) {
                for (OrderStore orderStore : list1) {
                    if (orderStore.getCouponId() == null) {
                        if (!StringUtils.isEmpty(orderStore.getCouponName())){
                            log.info("recove couponName code "+orderStore.getCouponName());
                            log.info("recove couponName code "+list.get(0).getGoodsId()+"");
                            activityService.addCode(orderStore.getCouponName(),list.get(0).getGoodsId()+"");
                        }
                    }
                }
            }
        }
    }

    public List<Trade> getAllByTradeStat(TradeEnum tradeEnum) {
        return tradeDao.getAllByTradeStat(tradeEnum.getCode());
    }


    public IPage query(Page page, OrderStoreCondition condition) {
        return orderStoreDao.query(page, condition);
    }


    public OrderDetailDo detail(long orderStoreId) {
        OrderStore orderStore = orderStoreDao.selectById(orderStoreId);
        if (orderStore == null) {
            throw new LsException(CodeEnum.ERROR, "该笔订单已经消失");
        }
        Store store = storeMapper.selectById(orderStore.getStoreId());
        Logistics logistics = logisticsMapper.selectById(orderStore.getLogisticsId());
        List<OrderGoods> list = orderGoodsDao.selectByOrderStoreId(orderStoreId);
        OrderDetailDo orderDetailDo = new OrderDetailDo();
        orderDetailDo.setStore(store);
        orderDetailDo.setLogistics(logistics);
        orderDetailDo.setOrderStore(orderStore);
        orderDetailDo.setOrderGoodsList(list);
        return orderDetailDo;
    }
}
